package com.jrfid.smartcabinet.demo.ui.take_or_add

import android.app.Application
import android.os.CountDownTimer
import android.view.View
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ToastUtils
import com.jrfid.devicemanager.library.CMDData
import com.jrfid.devicemanager.library.DeviceType
import com.jrfid.devicemanager.library.DevicesManager
import com.jrfid.devicemanager.library.packet.UHFPacketData
import com.jrfid.devicemanager.library.packet.UHFTagInfoModel
import com.jrfid.smartcabinet.demo.R
import com.jrfid.smartcabinet.demo.base.BaseViewModel
import com.jrfid.smartcabinet.demo.model.CabinetConfigInfoModel
import com.jrfid.smartcabinet.demo.model.SocketMsgModel
import com.jrfid.smartcabinet.demo.model.TagInfoModel
import com.jrfid.smartcabinet.demo.ui.taking.TakingFragmentArgs
import com.jrfid.smartcabinet.demo.utils.Config
import com.jrfid.smartcabinet.demo.utils.KTDataUtils
import com.jrfid.smartcabinet.demo.utils.TCPConnectUtils
import com.xuhao.didi.core.iocore.interfaces.ISendable
import com.xuhao.didi.core.pojo.OriginalData
import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo
import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager
import kotlinx.coroutines.*
import java.lang.Exception
import java.util.*
import kotlin.concurrent.timer
import kotlin.concurrent.timerTask
import kotlin.experimental.and
import kotlin.math.max
import kotlin.math.min

class TakeOrAddGoodsViewModel(application: Application, navController: NavController) : BaseViewModel(application, navController) {

    val isTake = ObservableBoolean(false)
    val startAnimation = MutableLiveData(false)
    var tipsText = ObservableField(StringUtils.getString(R.string.text_take_inventory_tips, 15))
    val showTipsDialog = MutableLiveData("")

    //    private val countDownTimer = object : CountDownTimer(1000 * 3, 250) {
//        override fun onTick(millisUntilFinished: Long) {
//            LogUtils.dTag(TAG, millisUntilFinished.toString())
//            managerList.forEach {
//                it.send(SocketMsgModel(CMDData.R2000.realTimeInventory()))
//            }
//            tipsText.set(StringUtils.getString(R.string.text_take_inventory_tips, (millisUntilFinished / 1000).toInt()))
//        }
//
//        override fun onFinish() {
//            managerList.forEach {
//                it.unRegisterReceiver(socketListener)
//                it.disconnect()
//            }
//            startAnimation.value = false
//            if (errorIPList.size == cabinetInfoList.size) {
//                showTipsDialog.value = getString(R.string.text_inventory_connect_error)
//            } else {
//                if (tagInfoList.isEmpty() && isTake.get()) {
//                    showTipsDialog.value = getString(R.string.text_inventory_empty_tag)
//                } else {
//                    val list = arrayListOf<CabinetConfigInfoModel>()
//                    if (errorIPList.isEmpty()) {
//                        list.addAll(cabinetInfoList)
//                    } else {
//                        cabinetInfoList.forEach { info ->
//                            if (errorIPList.find { it == info.readerIP.get() } == null) {
//                                list.add(info)
//                            }
//                        }
//                    }
//                    navController.navigate(
//                        R.id.action_takeOrAddGoodsFragment_to_takingFragment,
//                        TakingFragmentArgs(isTake = isTake.get(), tagInfoArray = tagInfoList.toTypedArray(), cabinetArray = list.toTypedArray()).toBundle()
//                    )
//                }
//            }
//        }
//
//    }
    private val cabinetInfoList = Config.getCabinetList()

    private val cabinetNameMap = hashMapOf<Int, String>()
    private val tagInfoList = arrayListOf<TagInfoModel>()
//    private val managerList = mutableListOf<IConnectionManager>()
//    private val errorIPList = arrayListOf<String>()
//    private val socketListener = object : SocketActionAdapter() {
//        override fun onSocketConnectionSuccess(info: ConnectionInfo, action: String?) {
//            super.onSocketConnectionSuccess(info, action)
//            errorIPList.remove(info.ip)
//        }
//
//        override fun onSocketConnectionFailed(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketConnectionFailed(info, action, e)
//            ToastUtils.showShort("${cabinetNameMap[info.ip]}${getString(R.string.text_connect_error)}")
//            errorIPList.add(info.ip)
//        }
//
//        override fun onSocketDisconnection(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketDisconnection(info, action, e)
//            ToastUtils.showShort("${cabinetNameMap[info.ip]}${getString(R.string.text_connect_error_disconnect)}")
//        }
//
//        override fun onSocketReadResponse(info: ConnectionInfo, action: String, data: OriginalData) {
//            super.onSocketReadResponse(info, action, data)
//            val body = data.bodyBytes
//            val header = data.headBytes
//            LogUtils.dTag(TAG, "${info.ip}收到数据：${KTDataUtils.byteArrayToHex(data.headBytes)} ${KTDataUtils.byteArrayToHex(data.bodyBytes)}")
//            if (header.size == 2 && header[1] > 0x0A) {
//                //读到标签
//                val len = header[1].toInt()
//                val epc = KTDataUtils.byteArrayToHexTrim(body.toList().subList(5, len - 2).toByteArray())
//                if (tagInfoList.find { it.epc == epc } == null) {
//                    val tagInfoModel = TagInfoModel().apply {
//                        this.cabinetName = cabinetNameMap[info.ip] ?: ""
//                        this.epc = epc
//                    }
//                    tagInfoList.add(tagInfoModel)
//                }
//            }
//        }
//
//        override fun onSocketWriteResponse(info: ConnectionInfo, action: String?, data: ISendable) {
//            super.onSocketWriteResponse(info, action, data)
//            LogUtils.dTag(TAG, "${info.ip}发送数据：${KTDataUtils.byteArrayToHex(data.parse())}")
//        }
//    }

    private val listener = object : DevicesManager.OnDeviceDataCallback {
        override fun onDataReceived(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {
            if (deviceType == DeviceType.UHF) {
                val model = UHFPacketData(byteArray)
                when (model.cmd) {
                    (0x89).toByte(), (0x8A).toByte(), (0x8B).toByte() -> {
                        //盘存标签
                        if (model.len < 10) {
                            //盘存错误
//                            if (address == 0x01.toByte()) {
//                                sendInventoryCMD1()
//                            } else if (address == 0x02.toByte()) {
//                                sendInventoryCMD2()
//                            }
                        } else if (model.len == 10) {
                            //盘存结束
//                            if (address == 0x01.toByte()) {
//                                sendInventoryCMD1()
//                            } else if (address == 0x02.toByte()) {
//                                sendInventoryCMD2()
//                            }
                        } else {
                            //盘存到标签
                            val tag = UHFTagInfoModel(model.data)
                            if (tag.rssi > -100) {
                                if (tagInfoList.find { it.epc == tag.epc } == null) {
                                    val tagInfoModel = TagInfoModel().apply {
                                        this.cabinetName = cabinetNameMap[address.toInt()] ?: ""
                                        this.epc = tag.epc
                                    }
                                    tagInfoList.add(tagInfoModel)
                                }
                            }
                        }
                    }
                }
            }
        }

        override fun onDataSend(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {

        }

    }

//    private val onReceiveMainBoardDataListener = object : Manager.OnSerialPortDataListener {
//
//        override fun onDataReceived(byteArray: ByteArray) {
//            LogUtils.d("main recv: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//            val len = byteArray[1].toInt()
//            val dataLen = len - 3
//            val cmd = byteArray[3]
//            val address = byteArray[2]
//            when (cmd) {
//                CMDData.Cabinet.CMD_UHF_DATA -> {
//                    val uhfData = ByteArray(dataLen)
//                    System.arraycopy(byteArray, 4, uhfData, 0, uhfData.size)
//                    onReceivedUHFData(address, uhfData)
//                }
//            }
//        }
//
//        override fun onDataSend(byteArray: ByteArray) {
//            LogUtils.d("main send: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//        }
//
//    }

//    private fun onReceivedUHFData(address: Byte, byteArray: ByteArray) {
//        val len = byteArray[1].toInt()
//        val cmd = byteArray[3]
//        when (cmd) {
//            (0x89).toByte(), (0x8A).toByte(), (0x8B).toByte() -> {
//                //盘存标签
//                if (len < 10) {
//                    //盘存错误
//                    if (address == 0x01.toByte()) {
//                        sendInventoryCMD1()
//                    } else if (address == 0x02.toByte()) {
//                        sendInventoryCMD2()
//                    }
//                } else if (len == 10) {
//                    //盘存结束
//                    if (address == 0x01.toByte()) {
//                        sendInventoryCMD1()
//                    } else if (address == 0x02.toByte()) {
//                        sendInventoryCMD2()
//                    }
//                } else {
//                    //盘存到标签
//                    val time = System.currentTimeMillis()
//                    val epcLen = len - 7
//                    val epcData = ByteArray(epcLen)
//                    System.arraycopy(byteArray, 7, epcData, 0, epcLen)
//                    val epc = KTDataUtils.byteArrayToHexTrim(epcData)
//                    val rssi = (byteArray[len] and 127) - 129
//                    if (rssi > -100) {
//                        if (tagInfoList.find { it.epc == epc } == null) {
//                            val tagInfoModel = TagInfoModel().apply {
//                                this.cabinetName = cabinetNameMap[address.toInt()] ?: ""
//                                this.epc = epc
//                            }
//                            tagInfoList.add(tagInfoModel)
//                        }
//                    }
//                }
//            }
//        }
//    }

    private var isInventorying = false
    private var retryInventoryJob1: Job? = null

    private fun sendInventoryCMD1() {
        retryInventoryJob1?.cancel()
        if (isInventorying) {
            DevicesManager.instance.sendData(
                DeviceType.UHF, 0x01,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(
                    session = 1,
                    ant4 = false,
                    ant5 = false,
                    ant6 = false,
                    ant7 = false
                )
            )
            retryInventoryJob1 = viewModelScope.launch {
                delay(300)
                sendInventoryCMD1()
            }
        }
    }

    private var retryInventoryJob2: Job? = null

    private fun sendInventoryCMD2() {
        retryInventoryJob2?.cancel()
        if (isInventorying) {
            DevicesManager.instance.sendData(
                DeviceType.UHF, 0x02,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(
                    session = 1,
                    ant7 = false
                )
            )
            retryInventoryJob2 = viewModelScope.launch {
                delay(300)
                sendInventoryCMD2()
            }
        }
    }

    private fun sendLoopInventory1() {
        if (isInventorying) {
            DevicesManager.instance.startInventory(
                5,
                address = 0x01,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(ant4 = false, ant5 = false, ant6 = false, ant7 = false, session = 1)
            )
        }
    }

    private fun sendLoopInventory2() {
        if (isInventorying) {
            DevicesManager.instance.startInventory(
                5,
                address = 0x02,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(ant7 = false, session = 1)
            )
        }
    }

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        DevicesManager.instance.addOnDeviceDataListener(listener)
//        MainBoardManager.instance.addOnSerialPortDataListener(onReceiveMainBoardDataListener)
        if (cabinetInfoList.isNotEmpty()) {
            startAnimation.value = true
            cabinetInfoList.forEach { model ->
                cabinetNameMap[model.address.get()!!.toInt()] = model.name.get()!!
//                val manager = TCPConnectUtils.connectRFIDDevice(model.readerIP.get(), model.readerPort.get()?.toIntOrNull(), socketListener)
//                managerList.add(manager)
            }
//            countDownTimer.start()
            viewModelScope.launch {
                isInventorying = true
                sendLoopInventory1()
                sendLoopInventory2()
//                sendInventoryCMD1()
//                sendInventoryCMD2()
                for (i in 5 downTo 0) {
                    withContext(Dispatchers.Main) {
                        tipsText.set(StringUtils.getString(R.string.text_take_inventory_tips, i))
                    }
                    delay(1000)
                }
                isInventorying = false
                if (tagInfoList.isEmpty() && isTake.get()) {
                    withContext(Dispatchers.Main) {
                        showTipsDialog.value = getString(R.string.text_inventory_empty_tag)
                    }
                } else {
                    withContext(Dispatchers.Main) {
                        navController.navigate(
                            R.id.action_takeOrAddGoodsFragment_to_takingFragment,
                            TakingFragmentArgs(isTake = isTake.get(), tagInfoArray = tagInfoList.toTypedArray(), cabinetArray = cabinetInfoList.toTypedArray()).toBundle()
                        )
                    }
                }
            }
        } else {
            ToastUtils.showLong(getString(R.string.text_config_cabinet_info))
        }
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        DevicesManager.instance.removeOnDeviceDataListener(listener)
//        MainBoardManager.instance.removeOnSerialPortDataListener(onReceiveMainBoardDataListener)
    }

    fun onClickBackBtn(view: View) {
        back()
    }

    fun back() {
//        countDownTimer.cancel()
//        managerList.forEach {
//            it.unRegisterReceiver(socketListener)
//        }
        navController.navigateUp()
    }

}